﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using IBupro.Controllers.Classes;
using IBupro.Models;
using iBuproModel;
using iBuproModel.Repositories.Interfaces;
using IBupro.Classes;
using System.Data.Objects.DataClasses;

namespace IBupro.Controllers
{
    public class StudentProjectController : CustomController
    {
        
        public ActionResult Index()
        {
            /*
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
            return View(projects.GetAll());
            */
            if (User.IsInRole("Student"))
                return RedirectToAction("Index","Student");
            if (User.IsInRole("Lector"))
                return RedirectToAction("Index", "Student");
            return RedirectToAction("ListProjects", "StudentProject");
        }


        /// <summary>
        /// Creates new Student Project
        /// </summary>
        /// <returns></returns>
        [Authorize(Roles="Lector")]
        public ActionResult Create()
        {
            return View(new StudentProjectModel());
        }

        /// <summary>
        /// Creates new Student Project
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector")]
        [HttpPost]
        public ActionResult Create(StudentProjectModel model)
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();

            if (ModelState.IsValid)
            {

                Project project = model.ModelToProject(users.GetUserByUserName(User.Identity.Name));
                IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
                projects.Add(project);
                projects.SaveChanges();
                return RedirectToAction("Index");
            }
            else
            {
                return View(model);
            }
        }


        /// <summary>
        /// Edits student project
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(Roles="Lector")]
        public ActionResult Edit(int id)
        {
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
            Project project = projects.First(p => p.Id == id);
            StudentProjectModel model = new StudentProjectModel();
            ITagRepository tags = repositoryService.TagRepositoryCreateInstance();

            model.Name = project.Name;
            model.MemberCount = project.MemberCount;
            model.ShortCut = project.Shortcut;
            model.Locked = (bool)project.Locked;
            model.Detail = project.Detail;
            model.SubjectId = project.Subject.Id;
            model.Tags = tags.TagsToString(project.Tags);
            if (model.Tags == null)
                model.Tags = "";
            

            
            return View(model);
        }


        /// <summary>
        /// Edits student project
        /// </summary>
        /// <param name="id"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector")]
        [HttpPost]
        public ActionResult Edit(int id, StudentProjectModel model)
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();

            if (ModelState.IsValid)
            {
                IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
                ISubjectRepository subjects = repositoryService.SubjectRepositoryCreateInstace();
                ITagRepository tags = repositoryService.TagRepositoryCreateInstance();
                Project oldProject = projects.First(p => p.Id == id);
                
                oldProject.Name = model.Name;
                oldProject.Locked = model.Locked;
                oldProject.Detail = model.Detail;
                oldProject.Subject = subjects.First(s => s.Id == id);
                oldProject.Shortcut = model.ShortCut;
                oldProject.MemberCount = model.MemberCount;


                tags.SaveTagsForProject(model.Tags, oldProject);

                projects.SaveChanges();
                return RedirectToAction("Detail",new {id = id});
            }
            else
            {
                if (model.Tags == null)
                    model.Tags = "";
                return View(model);
            }
        }


        /// <summary>
        /// Send subscription request
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector,Student")]
        public ActionResult SendSubscriptionRequest(int id)
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();

            User subscriber = users.GetUserByUserName(User.Identity.Name);
            Project project = projects.First(p => p.Id == id);

            
            
            if (project == null)
                throw new Exception("Cannot find user with specified ID");

            if (project.Users.Count >= project.MemberCount)
            {
                FlashMessenger.AddMessage("Project is full", MessageType.Error);
                return RedirectToAction("Index");
            }

            if (project.Locked == true)
            {
                FlashMessenger.AddMessage("Project is locked.", MessageType.Error);
                return RedirectToAction("Index");
            }

            if (project.Users.Contains(subscriber))
            {
                FlashMessenger.AddMessage("You are already subscribed in this project.", MessageType.Notice);
                return RedirectToAction("Index");
            }


            var alredyRequested = project.OwnerRequests.FirstOrDefault(r => r.User.Id == subscriber.Id);

            if (alredyRequested != null)
            {
                FlashMessenger.AddMessage("Cannot send more requests!",MessageType.Error);
                return RedirectToAction("Index");
            }

            OwnerRequest request = new OwnerRequest();
            request.Pending = true;
            request.Text = "";
            request.User = subscriber;
            project.OwnerRequests.Add(request);
            projects.SaveChanges();

            FlashMessenger.AddMessage("Your request has been send to project leader",MessageType.Notice);
            mailer.StudentRequestStudentProjectToLector(project, subscriber);
            
            return RedirectToAction("Index");
        }


        /// <summary>
        /// Accepts project request
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector")]
        public ActionResult AcceptRequest(int id)
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();
            IOwnerRequestRepository requests = repositoryService.OwnerRequestRepositoryCreateInstance();
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
            

            var request = requests.First(r => r.Id == id);
            User principal = request.Project.Principal;

            if (request == null)
            {
                throw new Exception("Cannot find owner request");
            }

            if (request.Project.Users.Count >= request.Project.MemberCount)
            {
                FlashMessenger.AddMessage("Project is full", MessageType.Error);
                return RedirectToAction("Index");
            }

            if (request.Project.Locked == true)
            {
                FlashMessenger.AddMessage("Project is locked.", MessageType.Error);
                return RedirectToAction("Index");
            }

            if (principal.Id != users.GetUserByUserName(User.Identity.Name).Id)
            {
                throw new Exception("This is not your request");
            }

            request.Project.Users.Add(request.User);
            request.Pending = false;
            requests.SaveChanges();

            mailer.LectorAcceptReplyStudentProjectRequest(request.Project, request.User);

            requests.Delete(request);

            requests.SaveChanges();

            FlashMessenger.AddMessage("User has been subscribed to student project.", MessageType.Success);
            

            return RedirectToAction("ListRequests","StudentProject");
            
        }


        /// <summary>
        /// Denies participation on project
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector")]
        public ActionResult DenyRequest(int id)
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();
            IOwnerRequestRepository requests = repositoryService.OwnerRequestRepositoryCreateInstance();
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();


            var request = requests.First(r => r.Id == id);
            User principal = request.Project.Principal;

            if (request == null)
            {
                throw new Exception("Cannot find this owner request");
            }

            if (principal.Id != users.GetUserByUserName(User.Identity.Name).Id)
            {
                throw new Exception("This is not your request");
            }

            mailer.LectorDenyReplyStudentProjectRequest(request.Project, request.User);

            requests.Delete(request);
            requests.SaveChanges();

            FlashMessenger.AddMessage("Request has been denied.", MessageType.Success);
            return RedirectToAction("Index");

        }


        /// <summary>
        /// Lists reuqests for student project
        /// </summary>
        /// <returns></returns>
        [Authorize(Roles = "Lector")]
        public ActionResult ListRequests()
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
            IOwnerRequestRepository requests = repositoryService.OwnerRequestRepositoryCreateInstance();

            User user = users.GetUserByUserName(User.Identity.Name);

            return View(requests.GetAll(r => r.Project.Principal.Id == user.Id));
        }


        /// <summary>
        /// Detail
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector, Student")]        
        public ActionResult Detail(int id)
        {
            return View(id);
        }

        /// <summary>
        /// Partial detail
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector, Student")]
        public ActionResult DetailPartial(int id)
        {
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
            var project = projects.First(p => p.Id == id);
            return View(project);
        }


        /// <summary>
        /// Rmoves user from project
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector,Student")]
        public ActionResult RemoveUserFromProject(int userId, int projectId)
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();

            Project project = projects.First(p => p.Id == projectId);



            // user is not subscribed in project or removing by project principal test
            if (!project.Users.Contains(users.GetUserByUserName(User.Identity.Name)) && (project.Principal.Username != User.Identity.Name))
            {
                throw new Exception("This is not your project.");
            }

            User userToDelete = users.First(u => u.Id == userId);

            if (!project.Users.Contains(userToDelete))
            {
                throw new Exception("User is not subscribed to project");
            }

            var validUsers = (from u in project.Users
                             where u.Id != userToDelete.Id
                             select u).ToList();

            project.Users.Clear();

            foreach (var u in validUsers)
            {
                project.Users.Add(u);
            }

            /*project.Users = project.Users.Where(u => u.Id != userToDelete.Id);*/
            

            
            projects.SaveChanges();

            FlashMessenger.AddMessage("User has been removed from project",MessageType.Success);

            return RedirectToAction("Detail","StudentProject",new {id = projectId});
        }


        /// <summary>
        /// Removes project
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(Roles = "Lector")]
        public ActionResult Remove(int id)
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();

            Project project = projects.First(p => p.Id == id);

            if (project == null)
            {
                throw new Exception("Not project found");
            }

            if (project.Principal.Username != User.Identity.Name)
            {
                throw new Exception("This is not your project.");
            }

            project.Users.Clear();

            projects.Delete(project);

            projects.SaveChanges();

            FlashMessenger.AddMessage("Project has been removed", MessageType.Success);

            return RedirectToAction("Index");
        }

        /// <summary>
        /// Projects that user has created
        /// </summary>
        [Authorize(Roles = "Lector")]
        public ActionResult MyProjects()
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
            User user = users.GetUserByUserName(User.Identity.Name);

            IEnumerable<Project> pom = projects.GetAll(p => p.Principal.Id == user.Id);

            return View(pom);
        }

        /// <summary>
        /// Subscribed projects for current user
        /// </summary>
        /// <returns></returns>
        [Authorize(Roles = "Lector,Student")]
        public ActionResult InvolvedProjects()
        {
            IUserRepository users = repositoryService.UserRepositoryCreateInstance();
            IProjectRepository projects = repositoryService.ProjectRepositoryCreateInstance();
            User user = users.GetUserByUserName(User.Identity.Name);

            return View(user.Projects);
        }


        /// <summary>
        /// Lists student projects for current user
        /// </summary>
        /// <returns></returns>
        [Authorize(Roles = "Lector")]        
        public ActionResult ListProjects()
        {
            return View();
        }

    }
}
